﻿using Controller.Utils;
using Leeder.Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ControllerManageServer.Handler
{
    /// <summary>
    /// 和爱鸥通讯的Socket处理器
    /// </summary>
    internal class AioiSocketClientHandler : SocketClientHandler
    {

        #region 变量声明

        /// <summary>
        /// 数据报文头
        /// </summary>
        public const byte HEAT = 0x02;
        /// <summary>
        /// 数据报文尾
        /// </summary>
        public const byte TAIL = 0x03;

        #endregion 变量声明

        #region 事件定义

        //      /// <summary>
        ///// 数据接收事件
        ///// </summary>
        //public new event Action<byte[]> OnDataReceive;

        #endregion 事件定义

        public AioiSocketClientHandler(string ip, int port)
        {
            IPAddress = ip;
            Port = port;
        }

        /// <summary>
        /// 报文解析
        /// </summary>
        /// <param name="iDatas"></param>
        /// <returns></returns>
        protected override byte[] ParsingPacket(byte[] iDatas)
        {
            int position = 0, length = iDatas.Length, dataActionLength;

            while (position < length)
            {
                // 如果拿到的第一次不是数据报文头则过滤掉该位
                while (position < length && iDatas[position] != HEAT)
                {
                    position++;
                }
                if (position > 0)
                {
                    logObj.Error($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} <> [Aoio][{IPAddress}:{Port}]接收解析 <-- 收到不符合数据报文头的报文数据:{ByteUtils.ByteArrayToHexString(iDatas, 0, position)}\r\n");
                    // 整个数据报文都没有数据报文头这一位
                    if (position == iDatas.Length) return new byte[0];
                }
                // 跳过不符合的报文
                length = iDatas.Length - position;
                iDatas = iDatas.Skip(position).Take(length).ToArray();
                position = 0;
                try
                {
                    // 报文的前8位分别是数据报文头(1)+序列号(3)+数据长度(4),所以如果数据长度小于8即没收全则不做处理
                    if (length < 8) return iDatas;
                    // 数据指令的长度
                    dataActionLength = ByteUtils.AsciiByteArrayToInt(iDatas, 4, 4);
                    if (dataActionLength < 0)
                    {
                        logObj.Error($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} <> [Aoio][{IPAddress}:{Port}]接收解析 <-- ASCII码转整形失败!{ByteUtils.ByteArrayToHexString(iDatas, 4, 4)}\r\n");
                        logObj.Error($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} <> [Aoio][{IPAddress}:{Port}]接收解析 <-- 数据指令长度小于0!移除当前数据报文头!{ByteUtils.ByteArrayToHexString(iDatas, 0, 1)}\r\n");
                        iDatas = iDatas.Skip(1).Take(length - 1).ToArray();
                        position = 0;
                        continue;
                    }
                    // 如果总报文长度不够,说明还没收全,则返回,报文的前8位+指令数据(dataActionLength)+数据报文尾(1)
                    if (length < dataActionLength + 9) return iDatas;
                    byte[] temp = iDatas.Skip(position).Take(dataActionLength + 9).ToArray();
                    // 数据接收处理
                    OnDataReceive(temp);
                    logObj.Debug($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} <> [Aoio][{IPAddress}:{Port}]接收 <-- {ByteUtils.ByteArrayToHexString(temp, 0, temp.Length)}\t{ByteUtils.ByteArrayToAsciiString(temp)}\r\n");
                    iDatas = iDatas.Skip(dataActionLength + 9).Take(length - dataActionLength - 9).ToArray();
                    position = 0;
                    length = iDatas.Length;
                }
                catch (Exception ex)
                {
                    logObj.Error(ExceptionType.BusinessException, ex, "parsing packet exception");
                }
            }
            return iDatas;
        }
    }
}
